<?php

namespace my\wechat;

class QyWeChat
{
    const API_URL_PREFIX = 'https://qyapi.weixin.qq.com/cgi-bin';
    const USER_CREATE_URL = '/user/create?';
    const USER_UPDATE_URL = '/user/update?';
    const USER_DELETE_URL = '/user/delete?';
    const USER_BATCHDELETE_URL = '/user/batchdelete?';
    const USER_GET_URL = '/user/get?';
    const USER_LIST_URL = '/user/simplelist?';
    const USER_LIST_INFO_URL = '/user/list?';
    const USER_GETINFO_URL = '/user/getuserinfo?';
    const USER_INVITE_URL = '/invite/send?';
    const DEPARTMENT_CREATE_URL = '/department/create?';
    const DEPARTMENT_UPDATE_URL = '/department/update?';
    const DEPARTMENT_DELETE_URL = '/department/delete?';
    const DEPARTMENT_MOVE_URL = '/department/move?';
    const DEPARTMENT_LIST_URL = '/department/list?';
    const TAG_CREATE_URL = '/tag/create?';
    const TAG_UPDATE_URL = '/tag/update?';
    const TAG_DELETE_URL = '/tag/delete?';
    const TAG_GET_URL = '/tag/get?';
    const TAG_ADDUSER_URL = '/tag/addtagusers?';
    const TAG_DELUSER_URL = '/tag/deltagusers?';
    const TAG_LIST_URL = '/tag/list?';
    const MEDIA_UPLOAD_URL = '/media/upload?';
    const MEDIA_GET_URL = '/media/get?';
    const AUTHSUCC_URL = '/user/authsucc?';
    const MASS_SEND_URL = '/message/send?';
    const MENU_CREATE_URL = '/menu/create?';
    const MENU_GET_URL = '/menu/get?';
    const MENU_DELETE_URL = '/menu/delete?';
    const TOKEN_GET_URL = '/gettoken?';
    const TICKET_GET_URL = '/get_jsapi_ticket?';
    const CALLBACKSERVER_GET_URL = '/getcallbackip?';
    const OAUTH_PREFIX = 'https://open.weixin.qq.com/connect/oauth2';
    const OAUTH_AUTHORIZE_URL = '/authorize?';
    const CHAT_CREATE_URL = '/chat/create?';
    const CHAT_GET_URL = '/chat/get?';
    const CHAT_UPDATE_URL = '/chat/update?';
    const CHAT_QUIT_URL = '/chat/quit?';
    const CHAT_CLEARNOTIFY_URL = '/chat/clearnotify?';
    const CHAT_SEND_URL = '/chat/send?';
    const CHAT_SETMUTE_URL = '/chat/setmute?';

    private $token;
    private $encodingAesKey;
    private $appid;         //也就是企业号的CorpID
    private $appsecret;
    private $access_token;
    private $agentid;       //应用id   AgentID
    private $postxml;
    private $agentidxml;    //接收的应用id   AgentID
    private $jsapi_ticket;

    public $debug = false;
    public $errCode = 40001;
    public $errMsg = "no access";
    public $im = false;

    public function __construct($options)
    {
        $this->token = isset($options['token']) ? $options['token'] : '';
        $this->encodingAesKey = isset($options['encodingaeskey']) ? $options['encodingaeskey'] : '';
        $this->appid = isset($options['appid']) ? $options['appid'] : '';
        $this->appsecret = isset($options['appsecret']) ? $options['appsecret'] : '';
        $this->agentid = isset($options['agentid']) ? $options['agentid'] : '';
        $this->debug = isset($options['debug']) ? $options['debug'] : false;

        $this->im = isset($options['im']) ? $options['im'] : false;
    }

    protected function log($log)
    {
        if ($this->debug) {
            if (is_array($log)) $log = print_r($log, true);
            return trace($log);
        }

        return true;
    }

    /**
     * 微信api不支持中文转义的json结构
     * @param $arr
     * @return string
     */
    static function json_encode($arr)
    {
        $parts = array();
        $is_list = false;
        //Find out if the given array is a numerical array
        $keys = array_keys($arr);
        $max_length = count($arr) - 1;
        if (($keys [0] === 0) && ($keys [$max_length] === $max_length)) { //See if the first key is 0 and last key is length - 1
            $is_list = true;
            for ($i = 0; $i < count($keys); $i++) { //See if each key correspondes to its position
                if ($i != $keys [$i]) { //A key fails at position check.
                    $is_list = false; //It is an associative array.
                    break;
                }
            }
        }
        foreach ($arr as $key => $value) {
            if (is_array($value)) { //Custom handling for arrays
                if ($is_list)
                    $parts [] = self::json_encode($value); /* :RECURSION: */
                else
                    $parts [] = '"' . $key . '":' . self::json_encode($value); /* :RECURSION: */
            } else {
                $str = '';
                if (!$is_list)
                    $str = '"' . $key . '":';
                //Custom handling for multiple data types
                if (!is_string($value) && is_numeric($value) && $value < 2000000000)
                    $str .= $value; //Numbers
                elseif ($value === false)
                    $str .= 'false'; //The booleans
                elseif ($value === true)
                    $str .= 'true';
                else
                    $str .= '"' . addcslashes($value, "\\\"\n\r\t/") . '"'; //All other things
                $parts [] = $str;
            }
        }
        $json = implode(',', $parts);
        if ($is_list)
            return '[' . $json . ']'; //Return numerical JSON
        return '{' . $json . '}'; //Return associative JSON
    }

    /**
     * GET 请求
     * @param $url
     * @return bool|mixed
     */
    private function http_get($url)
    {
        $oCurl = curl_init();
        if (stripos($url, "https://") !== FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        if (intval($aStatus["http_code"]) == 200) {
            return $sContent;
        } else {
            return false;
        }
    }

    /**
     * POST 请求
     * @param string $url
     * @param array $param
     * @param boolean $post_file 是否文件上传
     * @return string content
     */
    private function http_post($url, $param, $post_file = false)
    {
        $oCurl = curl_init();
        if (stripos($url, "https://") !== FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        if (is_string($param) || $post_file) {
            $strPOST = $param;
        } else {
            $aPOST = array();
            foreach ($param as $key => $val) {
                $aPOST[] = $key . "=" . urlencode($val);
            }
            $strPOST = join("&", $aPOST);
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($oCurl, CURLOPT_POST, true);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS, $strPOST);
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        if (intval($aStatus["http_code"]) == 200) {
            return $sContent;
        } else {
            return false;
        }
    }

    /**
     * For weixin server validation
     * @param $str
     * @return bool
     */
    private function checkSignature($str)
    {
        $signature = isset($_GET["msg_signature"]) ? $_GET["msg_signature"] : '';
        $timestamp = isset($_GET["timestamp"]) ? $_GET["timestamp"] : '';
        $nonce = isset($_GET["nonce"]) ? $_GET["nonce"] : '';
        $tmpArr = array($str, $this->token, $timestamp, $nonce);//比普通公众平台多了一个加密的密文
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $shaStr = sha1($tmpStr);
        if ($shaStr == $signature) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 微信验证，包括post来的xml解密
     * @param bool $return
     * @return bool
     */
    public function valid($return = false)
    {
        $encryptStr = "";
        if ($_SERVER['REQUEST_METHOD'] == "POST") {
            $postStr = file_get_contents("php://input");
            $array = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $this->log($postStr);
            if (isset($array['Encrypt'])) {
                $encryptStr = $array['Encrypt'];
                $this->agentidxml = isset($array['AgentID']) ? $array['AgentID'] : '';
            }
        } else {
            $encryptStr = isset($_GET["echostr"]) ? $_GET["echostr"] : '';
        }
        if ($encryptStr) {
            $ret = $this->checkSignature($encryptStr);
        }
        if (!isset($ret) || !$ret) {
            if (!$return) {
                die('no access');
            } else {
                return false;
            }
        }
        $pc = new Prpcrypt($this->encodingAesKey);
        $array = $pc->decrypt($encryptStr, $this->appid);
        if (!isset($array[0]) || ($array[0] != 0)) {
            if (!$return) {
                die('解密失败！');
            } else {
                return false;
            }
        }
        if ($_SERVER['REQUEST_METHOD'] == "POST") {
            $this->postxml = $array[1];
            //$this->log($array[1]);
            return ($this->postxml != "");
        } else {
            $echoStr = $array[1];
            if ($return) {
                return $echoStr;
            } else {
                die($echoStr);
            }
        }
    }

    /**
     * 设置缓存，按需重载
     * @param string $cachename
     * @param mixed $value
     * @param int $expired
     * @return boolean
     */
    protected function setCache($cachename, $value, $expired)
    {
        return cache($cachename, $value, $expired);
    }

    /**
     * 获取缓存，按需重载
     * @param string $cachename
     * @return mixed
     */
    protected function getCache($cachename)
    {
        return cache($cachename);
    }

    /**
     * 清除缓存，按需重载
     * @param string $cachename
     * @return boolean
     */
    protected function removeCache($cachename)
    {
        return cache($cachename, null);
    }

    /**
     * 通用auth验证方法
     * @param string $appid
     * @param string $appsecret
     * @param string $token 手动指定access_token，非必要情况不建议用
     * @return bool|mixed|string
     */
    public function checkAuth($appid = '', $appsecret = '', $token = '')
    {
        if (!$appid || !$appsecret) {
            $appid = $this->appid;
            $appsecret = $this->appsecret;
        }
        if ($token) { //手动指定token，优先使用
            $this->access_token = $token;
            return $this->access_token;
        }
        if ($this->im === true)
            $authname = 'qywechat_im_access_token' . $appid;
        else
            $authname = 'qywechat_access_token' . $appid;
        if ($rs = $this->getCache($authname)) {
            $this->access_token = $rs;
            return $rs;
        }
        $result = $this->http_get(self::API_URL_PREFIX . self::TOKEN_GET_URL . 'corpid=' . $appid . '&corpsecret=' . $appsecret);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            $this->access_token = $json['access_token'];
            $expire = $json['expires_in'] ? intval($json['expires_in']) - 100 : 3600;
            $this->setCache($authname, $this->access_token, $expire);
            return $this->access_token;
        }
        return false;
    }

    /**
     * 删除验证数据
     * @param string $appid
     * @return bool
     */
    public function resetAuth($appid = '')
    {
        if (!$appid) $appid = $this->appid;
        $this->access_token = '';
        $authname = 'qywechat_access_token' . $appid;
        $this->removeCache($authname);
        return true;
    }

    /**
     * 删除JSAPI授权TICKET
     * @param string $appid 用于多个appid时使用
     * @return bool
     */
    public function resetJsTicket($appid = '')
    {
        if (!$appid) $appid = $this->appid;
        $this->jsapi_ticket = '';
        $authname = 'qywechat_jsapi_ticket' . $appid;
        $this->removeCache($authname);
        return true;
    }

    /**
     * 获取JSAPI授权TICKET
     * @param string $appid 用于多个appid时使用,可空
     * @param string $jsapi_ticket 手动指定jsapi_ticket，非必要情况不建议用
     * @return bool|mixed|string
     */
    public function getJsTicket($appid = '', $jsapi_ticket = '')
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        if (!$appid) $appid = $this->appid;
        if ($jsapi_ticket) { //手动指定token，优先使用
            $this->jsapi_ticket = $jsapi_ticket;
            return $this->jsapi_ticket;
        }
        $authname = 'qywechat_jsapi_ticket' . $appid;
        if ($rs = $this->getCache($authname)) {
            $this->jsapi_ticket = $rs;
            return $rs;
        }
        $result = $this->http_get(self::API_URL_PREFIX . self::TICKET_GET_URL . 'access_token=' . $this->access_token);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            $this->jsapi_ticket = $json['ticket'];
            $expire = $json['expires_in'] ? intval($json['expires_in']) - 100 : 3600;
            $this->setCache($authname, $this->jsapi_ticket, $expire);
            return $this->jsapi_ticket;
        }
        return false;
    }

    /**
     * 获取JsApi使用签名
     * @param string $url 网页的URL，自动处理#及其后面部分
     * @param int $timestamp 当前时间戳 (为空则自动生成)
     * @param string $noncestr 随机串 (为空则自动生成)
     * @param string $appid 用于多个appid时使用,可空
     * @return array|bool 返回签名字串
     * @return array|bool
     */
    public function getJsSign($url, $timestamp = 0, $noncestr = '', $appid = '')
    {
        if (!$this->jsapi_ticket && !$this->getJsTicket($appid) || !$url) return false;
        if (!$timestamp)
            $timestamp = time();
        if (!$noncestr)
            $noncestr = $this->generateNonceStr();
        $ret = strpos($url, '#');
        if ($ret)
            $url = substr($url, 0, $ret);
        $url = trim($url);
        if (empty($url))
            return false;
        $arrdata = array("timestamp" => $timestamp, "noncestr" => $noncestr, "url" => $url, "jsapi_ticket" => $this->jsapi_ticket);
        $sign = $this->getSignature($arrdata);
        if (!$sign)
            return false;
        $signPackage = array(
            "appid" => $this->appid,
            "noncestr" => $noncestr,
            "timestamp" => $timestamp,
            "url" => $url,
            "signature" => $sign
        );
        return $signPackage;
    }

    /**
     * 获取签名
     * @param array $arrdata 签名数组
     * @param string $method 签名方法
     * @return boolean|string 签名值
     */
    public function getSignature($arrdata, $method = "sha1")
    {
        if (!function_exists($method)) return false;
        ksort($arrdata);
        $paramstring = "";
        foreach ($arrdata as $key => $value) {
            if (strlen($paramstring) == 0)
                $paramstring .= $key . "=" . $value;
            else
                $paramstring .= "&" . $key . "=" . $value;
        }
        $Sign = $method($paramstring);
        return $Sign;
    }

    /**
     * 生成随机字串
     * @param int $length 长度，默认为16，最长为32字节
     * @return string
     */
    public function generateNonceStr($length = 16)
    {
        // 密码字符集，可任意添加你需要的字符
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= $chars[mt_rand(0, strlen($chars) - 1)];
        }
        return $str;
    }

    /**
     * 上传多媒体文件 (只有三天的有效期，过期自动被删除)
     * @param $data
     * @param $type
     * @return bool|mixed
     */
    public function uploadMedia($data, $type)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::MEDIA_UPLOAD_URL . 'access_token=' . $this->access_token . '&type=' . $type, $data, true);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 根据媒体文件ID获取媒体文件
     * @param $media_id
     * @return bool|mixed
     */
    public function getMedia($media_id)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::MEDIA_GET_URL . 'access_token=' . $this->access_token . '&media_id=' . $media_id);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return $result;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $result;
        }
        return false;
    }

    /**
     * 创建部门
     * @param $data
     * @return bool|mixed
     */
    public function createDepartment($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::DEPARTMENT_CREATE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 更新部门
     * @param $data
     * @return bool|mixed
     */
    public function updateDepartment($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::DEPARTMENT_UPDATE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 删除部门
     * @param $id
     * @return bool|mixed
     */
    public function deleteDepartment($id)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::DEPARTMENT_DELETE_URL . 'access_token=' . $this->access_token . '&id=' . $id);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 移动部门
     * @param $data
     * @return bool|mixed
     */
    public function moveDepartment($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::DEPARTMENT_MOVE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 获取部门列表
     * @return bool|mixed
     */
    public function getDepartment()
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::DEPARTMENT_LIST_URL . 'access_token=' . $this->access_token);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 创建成员
     * @param $data
     * @return bool|mixed
     */
    public function createUser($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::USER_CREATE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 更新成员
     * @param $data
     * @return bool|mixed
     */
    public function updateUser($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::USER_UPDATE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 删除成员
     * @param $userid
     * @return bool|mixed
     */
    public function deleteUser($userid)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::USER_DELETE_URL . 'access_token=' . $this->access_token . '&userid=' . $userid);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 批量删除成员
     * @param $userids
     * @return bool|mixed
     */
    public function deleteUsers($userids)
    {
        if (!$userids) return false;
        $data = array('useridlist' => $userids);
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::USER_BATCHDELETE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 获取成员信息
     * @param $userid
     * @return bool|mixed
     */
    public function getUserInfo($userid)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::USER_GET_URL . 'access_token=' . $this->access_token . '&userid=' . $userid);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 获取部门成员
     * @param $department_id
     * @param int $fetch_child
     * @param int $status
     * @return bool|mixed
     */
    public function getUserList($department_id, $fetch_child = 0, $status = 0)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::USER_LIST_URL . 'access_token=' . $this->access_token
            . '&department_id=' . $department_id . '&fetch_child=' . $fetch_child . '&status=' . $status);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 获取部门成员详情
     * @param $department_id
     * @param int $fetch_child
     * @param int $status
     * @return bool|mixed
     */
    public function getUserListInfo($department_id, $fetch_child = 0, $status = 0)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::USER_LIST_INFO_URL . 'access_token=' . $this->access_token
            . '&department_id=' . $department_id . '&fetch_child=' . $fetch_child . '&status=' . $status);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 根据code获取成员信息
     * @param $code
     * @param int $agentid
     * @return bool|mixed
     */
    public function getUserId($code, $agentid = 0)
    {
        if (!$agentid) $agentid = $this->agentid;
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::USER_GETINFO_URL . 'access_token=' . $this->access_token . '&code=' . $code . '&agentid=' . $agentid);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 邀请成员关注
     * @param $userid
     * @param string $invite_tips
     * @return bool|mixed
     */
    public function sendInvite($userid, $invite_tips = '')
    {
        $data = array('userid' => $userid);
        if (!$invite_tips) {
            $data['invite_tips'] = $invite_tips;
        }
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::USER_INVITE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 创建标签
     * @param $data
     * @return bool|mixed
     */
    public function createTag($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::TAG_CREATE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 更新标签
     * @param $data
     * @return bool|mixed
     */
    public function updateTag($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::TAG_UPDATE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 删除标签
     * @param $tagid
     * @return bool|mixed
     */
    public function deleteTag($tagid)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::TAG_DELETE_URL . 'access_token=' . $this->access_token . '&tagid=' . $tagid);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 获取标签成员
     * @param $tagid
     * @return bool|mixed
     */
    public function getTag($tagid)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::TAG_GET_URL . 'access_token=' . $this->access_token . '&tagid=' . $tagid);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 增加标签成员
     * @param $data
     * @return bool|mixed
     */
    public function addTagUser($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::TAG_ADDUSER_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 删除标签成员
     * @param $data
     * @return bool|mixed
     */
    public function delTagUser($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::TAG_DELUSER_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 获取标签列表
     * @return bool|mixed
     */
    public function getTagList()
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::TAG_LIST_URL . 'access_token=' . $this->access_token);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 主动发送信息接口
     * @param $data
     * @return bool|mixed
     */
    public function sendMessage($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::MASS_SEND_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 二次验证
     * @param $userid
     * @return bool|mixed
     */
    public function authSucc($userid)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::AUTHSUCC_URL . 'access_token=' . $this->access_token . '&userid=' . $userid);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * oauth 授权跳转接口
     * @param string $callback 回调URI
     * @param string $state 重定向后会带上state参数，企业可以填写a-zA-Z0-9的参数值
     * @param string $scope
     * @return string
     */
    public function getOauthRedirect($callback, $state = 'STATE', $scope = 'snsapi_base')
    {
        return self::OAUTH_PREFIX . self::OAUTH_AUTHORIZE_URL . 'appid=' . $this->appid . '&redirect_uri=' . urlencode($callback) . '&response_type=code&scope=' . $scope . '&state=' . $state . '#wechat_redirect';
    }

    /**
     * 成员登录授权
     * @param $auth_code
     * @return bool|mixed
     * @author wb <pithyone@vip.qq.com>
     */
    public function getLoginInfo($auth_code)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . '/service/get_login_info?access_token=' . $this->access_token, self::json_encode(['auth_code' => $auth_code]));
        if ($result) {
            $json = json_decode($result, true);
            return $json;
        }
        return false;
    }

    /**
     * 创建会话
     * @param array $data 结构体为:
     * @return bool|mixed
     * @author wb <pithyone@vip.qq.com>
     */
    public function createChat($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::CHAT_CREATE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 获取会话
     * @param $chatid
     * @return bool|mixed
     */
    public function getChatInfo($chatid)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX . self::CHAT_GET_URL . 'access_token=' . $this->access_token . '&chatid=' . $chatid);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 修改会话信息
     * @param $data
     * @return bool|mixed
     * @author wb <pithyone@vip.qq.com>
     */
    public function updateChat($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::CHAT_UPDATE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 退出会话
     * @param $data
     * @return bool|mixed
     * @author wb <pithyone@vip.qq.com>
     */
    public function quitChat($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::CHAT_QUIT_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 清除会话未读状态
     * @param $data
     * @return bool|mixed
     * @author wb <pithyone@vip.qq.com>
     */
    public function clearnotifyChat($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::CHAT_CLEARNOTIFY_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 会话发消息
     * @param $data
     * @return bool|mixed
     * @author wb <pithyone@vip.qq.com>
     */
    public function sendChat($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::CHAT_SEND_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }

    /**
     * 设置成员新消息免打扰
     * @param $data
     * @return bool|mixed
     * @author wb <pithyone@vip.qq.com>
     */
    public function setmuteChat($data)
    {
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX . self::CHAT_SETMUTE_URL . 'access_token=' . $this->access_token, self::json_encode($data));
        if ($result) {
            $json = json_decode($result, true);
            if (!$json)
                return false;

            if (isset($json['errcode']) && !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json;
        }
        return false;
    }
}

